package com.lvmama.rhino.service.impl.comment;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.lvmama.rhino.mapperComment.ProductPredictMapper;
import com.lvmama.rhino.pojo.comment.Enum.EnumForCategory;
import com.lvmama.rhino.pojo.comment.Enum.EnumForFavorRate;
import com.lvmama.rhino.pojo.comment.Enum.EnumForWeek;
import com.lvmama.rhino.pojo.comment.entity.vo.*;
import com.lvmama.rhino.pojo.comment.request.PredictFavorRateRequest;
import com.lvmama.rhino.pojo.comment.request.PredictSalesNumRequest;
import com.lvmama.rhino.service.comment.PredictService;
import com.lvmama.rhino.utils.Constants;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * 产品预测
 */

@Service
@Transactional
public class PredictServiceImpl implements PredictService {

    @Autowired
    private ProductPredictMapper productPredictMapper;

    /**
     * 1.产品购买量预测
     *
     * @param request
     * @return
     * @throws Exception
     */
    @Override
    public PageInfo<ProPredictCalcResultVO> getPredictSalesNum(PredictSalesNumRequest request) throws Exception {
        PageInfo<ProPredictCalcResultVO> list = new PageInfo();
        getPredictPage(request);
        PageHelper.startPage(request.getCurrentPage(), request.getPageSize());
        request.setOrderBegin(-1);
        request.setOrderEnd(-1);
        PageInfo<Long> productIds = new PageInfo<>(productPredictMapper.getPredictSalesNumProductId(request));
        if (null == productIds && CollectionUtils.isEmpty(productIds.getList())) return null;
        List<ProPredictVO> predictList = productPredictMapper.getPredictSalesNumDetail(productIds.getList());

        // 枚举转换
        if (null != predictList && !CollectionUtils.isEmpty(predictList)) {
            for (int i = 0; i < predictList.size(); i++) {
                ProPredictVO vo = predictList.get(i);
                // 星期
                vo.setWeekName(EnumForWeek.getWeekShowname(vo.getWeek()));
                // 产品名称
                vo.setProductName(getProductName(vo.getProductName()));
                // 品类名称
                vo.setCategoryName(getCategoryName(vo.getCategoryId()));
            }
            // 合并数据
            List<ProPredictCalcResultVO> voList = mergePredictResult(productIds.getList(), predictList);
            BeanUtils.copyProperties(productIds, list, "list");
            list.setList(voList);
            // 数据处理(保留7条)
            calcPredictResultData(list.getList());
        }
        return list;
    }

    /**
     * 1. 数据处理
     *
     * @param list
     */
    private void calcPredictResultData(List<ProPredictCalcResultVO> list) {
        for (int i = 0; i < list.size(); i++) {
            ProPredictCalcResultVO vo = list.get(i);
            List<ProPredictVO> proVoList = vo.getPredictList();
            if (CollectionUtils.isEmpty(proVoList) || Constants.PRE_NUM == proVoList.size()) return;
            if (proVoList.size() > Constants.PRE_NUM) {
                int mar = proVoList.size() - Constants.PRE_NUM;
                for (int j = 0; j < proVoList.size(); mar--) {
                    if (mar == 0) break;
                    proVoList.remove(j);
                }
            } else if (proVoList.size() < Constants.PRE_NUM) {
                paddingPredictResultData(proVoList);
            }
            vo.setForOrder(proVoList.size());
        }
    }

    /**
     * 2. 填充不足的数据
     *
     * @param proVoList
     */
    private void paddingPredictFavorRateResultData(List<ProPredictFavorRateVO> proVoList) {
        int mar = Constants.PRE_NUM - proVoList.size();
        ProPredictFavorRateVO vo = new ProPredictFavorRateVO();
        BeanUtils.copyProperties(proVoList.get(0), vo, "goodRate", "date", "goodRateName", "lastFavorate", "lastDate");
        while (mar > 0) {
            mar--;
            proVoList.add(vo);
        }
    }

    /**
     * 1. 填充不足的数据
     *
     * @param proVoList
     */
    private void paddingPredictResultData(List<ProPredictVO> proVoList) {
        int mar = Constants.PRE_NUM - proVoList.size();
        ProPredictVO vo = new ProPredictVO();
        BeanUtils.copyProperties(proVoList.get(0), vo, "lastDate", "lastPurchases", "week", "weekName", "date", "salesNum");
        while (mar > 0) {
            mar--;
            proVoList.add(vo);
        }
    }

    /**
     * 1.合并数据
     *
     * @return
     */
    private List<ProPredictCalcResultVO> mergePredictResult(List<Long> list, List<ProPredictVO> predictList) {
        List<ProPredictCalcResultVO> resultVOList = new ArrayList<>();

        for (int i = 0; i < list.size(); i++) {
            Long productId = list.get(i);
            ProPredictCalcResultVO calcVo = new ProPredictCalcResultVO();
            calcVo.setProductId(productId);
            List<ProPredictVO> predictVOList = new ArrayList<>();
            for (int j = 0; j < predictList.size(); j++) {
                ProPredictVO vo = predictList.get(j);
                if (productId.equals(vo.getProductId())) {
                    BeanUtils.copyProperties(vo, calcVo);
                    ProPredictVO proPredictVO = new ProPredictVO();
                    BeanUtils.copyProperties(vo, proPredictVO);
                    predictVOList.add(proPredictVO);
                }
            }
            calcVo.setPredictList(predictVOList);
            calcVo.setForOrder(predictVOList.size());
            resultVOList.add(calcVo);
        }
        return resultVOList;
    }

    /**
     * 2.产品好评率预测
     *
     * @param request
     * @return
     */
    @Override
    public PageInfo<FavorRatePredictResultVO> getPredictFavorRate(PredictFavorRateRequest request) throws Exception {

        PageHelper.startPage(request.getCurrentPage(), request.getPageSize());
        PageInfo<Long> productIds = new PageInfo<>(productPredictMapper.getPredictFavorRateProductId(request));
        if (null == productIds && CollectionUtils.isEmpty(productIds.getList())) return null;
        List<ProPredictFavorRateVO> predictList = productPredictMapper.getPredictFavorRateDetail(productIds.getList());
        PageInfo<FavorRatePredictResultVO> list = new PageInfo<>();

//        PageHelper.startPage(request.getCurrentPage(), request.getPageSize());
//        PageInfo<ProPredictFavorRateVO> list = new PageInfo<>(productPredictMapper.getPredictFavorRate());
        // 枚举转换
        if (!CollectionUtils.isEmpty(predictList)) {
            for (int i = 0; i < predictList.size(); i++) {
                ProPredictFavorRateVO vo = predictList.get(i);
                // 产品名称
                vo.setProductName(getProductName(vo.getProductName()));
                // 品类名称
                vo.setCategoryName(getCategoryName(vo.getCategoryId()));
                // 预测好评率
                vo.setGoodRateName(EnumForFavorRate.getFavorRateName(vo.getGoodRate()));
            }
            // 合并数据

            List<FavorRatePredictResultVO> voList = mergePredictFavorRateResult(productIds.getList(), predictList);
            BeanUtils.copyProperties(productIds, list, "list");
            list.setList(voList);
            // 数据处理(保留7条)
            calcPredictFavorRateResultData(list.getList());
        }
        return list;
    }

    /**
     * 2. 数据处理
     *
     * @param list
     */
    private void calcPredictFavorRateResultData(List<FavorRatePredictResultVO> list) {
        for (int i = 0; i < list.size(); i++) {
            FavorRatePredictResultVO vo = list.get(i);
            List<ProPredictFavorRateVO> favorRateList = vo.getPredictList();
            if (CollectionUtils.isEmpty(favorRateList) || Constants.PRE_NUM == favorRateList.size()) return;
            if (favorRateList.size() > Constants.PRE_NUM) {
                int mar = favorRateList.size() - Constants.PRE_NUM;
                for (int j = 0; j < favorRateList.size(); mar--) {
                    if (mar == 0) break;
                    favorRateList.remove(j);
                }
            } else if (favorRateList.size() < Constants.PRE_NUM) {
                paddingPredictFavorRateResultData(favorRateList);
            }
            vo.setPredictListNum(favorRateList.size());
        }
    }

    /**
     * 2.合并数据
     *
     * @param list
     * @param predictList
     * @return
     */
    private List<FavorRatePredictResultVO> mergePredictFavorRateResult(List<Long> list, List<ProPredictFavorRateVO> predictList) {
        List<FavorRatePredictResultVO> resultVOList = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            Long productId = list.get(i);
            FavorRatePredictResultVO calcVo = new FavorRatePredictResultVO();
            calcVo.setProductId(productId);
            List<ProPredictFavorRateVO> predictVOList = new ArrayList<>();
            for (int j = 0; j < predictList.size(); j++) {
                ProPredictFavorRateVO vo = predictList.get(j);
                if (productId.equals(vo.getProductId())) {
                    BeanUtils.copyProperties(vo, calcVo);
                    ProPredictFavorRateVO proPredictVO = new ProPredictFavorRateVO();
                    BeanUtils.copyProperties(vo, proPredictVO);
                    predictVOList.add(proPredictVO);
                }
            }
            calcVo.setPredictList(predictVOList);
            calcVo.setPredictListNum(predictVOList.size());
            resultVOList.add(calcVo);
        }
        return resultVOList;
    }


    /**
     * 1-1. 产品需求量预测趋势图
     *
     * @param request
     * @return
     * @throws Exception
     */
    @Override
    public JSONArray getPredictSalesNumChart(PredictSalesNumRequest request) throws Exception {
        JSONArray jsonArray = new JSONArray();
        List<PredictSalesNumChartVO> voList = productPredictMapper.getPredictSalesNumChart(request);
        for (PredictSalesNumChartVO vo : voList) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("预测时间", vo.getDate());
            jsonObject.put("预测需求量", vo.getSalesNum());
            jsonArray.add(jsonObject);
        }
        return jsonArray;
    }

    /**
     * 2-2. 产品好评率预测趋势图
     *
     * @param request
     * @return
     * @throws Exception
     */
    @Override
    public JSONArray getPredictFavorRateChart(PredictFavorRateRequest request) throws Exception {
        JSONArray jsonArray = new JSONArray();
        List<PredictFavorRateChartVO> voList = productPredictMapper.getPredictFavorRateChart(request);
        for (PredictFavorRateChartVO vo : voList) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("预测时间", vo.getDate());
            jsonObject.put("预测好评率", vo.getGoodRate());
            jsonArray.add(jsonObject);
        }
        return jsonArray;
    }

    // 每页查询三个产品
    private void getPredictPage(PredictSalesNumRequest request) {
        int curr = request.getCurrentPage();
        int size = request.getPageSize();
        int orderEnd = curr * size - 1;
        int orderBegin = (curr - 1) * size;
        request.setOrderBegin(orderBegin);
        request.setOrderEnd(orderEnd);
    }

    public String getProductName(String productName) {
        if (StringUtils.isBlank(productName)) {
            productName = Constants.UNKNOWN;
        } else if (Constants.UNKNOWNDATA.equals(productName.trim()) ||
                Constants.UNKNOWNDATA2.equals(productName.trim()) ||
                Constants.UNKNOWNDATA3.equalsIgnoreCase(productName.trim())) {
            productName = Constants.UNKNOWN;
        }
        return productName;
    }

    public String getCategoryName(String categoryId) {
        String categoryName = Constants.UNKNOWN;
        if (!Constants.UNKNOWNDATA.equals(categoryId)) {
            categoryName = StringUtils.isNotBlank(categoryId) ? EnumForCategory.getCategoryShowName(categoryId) : null;
            if (StringUtils.isBlank(categoryName)) {
                categoryName = EnumForCategory.getCategoryName(categoryId);
            }
        }
        return categoryName;
    }
}
